home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Topik / Topik - Disk 09 - Business Work (19xx)(Topik Public Domain)(PD)[WB].zip / Topik - Disk 09 - Business Work (19xx)(Topik Public Domain)(PD)[WB].adf / C / qcat.c < prev    next >
C/C++ Source or Header  |  1989-07-14  |  12KB  |  561 lines

  1.  
  2. /***********************************************************************
  3.  
  4.     11/88
  5.  
  6.     QCAT v0.01 -- List files on disks or in directories
  7.  
  8.                          -----------------
  9.  
  10.                    Copyright (C) 1988 by Daniel Elbaum
  11.  
  12.          This software is freely redistributable provided that:
  13.          the three files which comprise it (qcat, qcat.c, qcat.doc)
  14.          remain intact; all copyright notices contained in any of
  15.          the aforementioned files remain intact; and no fee beyond
  16.          reasonable remuneration for collation and distribution be
  17.          charged for use and/or purveyance.
  18.  
  19. ***********************************************************************/
  20.  
  21. #include <stdio.h>
  22. #include <exec/types.h>
  23. #include <exec/memory.h>
  24. #include <libraries/dos.h>
  25. #include <libraries/dosextens.h>
  26. #include <intuition/intuition.h>
  27.  
  28. /* Error descriptor codes */
  29.  
  30. #define E_NOLOCK    (-1)
  31. #define E_NOMEM     (-2)
  32. #define E_NOEXAM    (-3)
  33. #define E_USAGE     (-4)
  34. #define E_OUTPUT    (-5)
  35. #define E_LIBRARY   (-6)
  36. #define E_NONODE    (-100)
  37. #define E_NOSTRING  (-101)
  38.  
  39. /* Manifest constants */
  40.  
  41. #define NAMSIZ      (108)
  42. #define MEMFLOOR    (64000L)    /* least amt of mem to leave    */
  43.  
  44. #define IREV    (1)
  45. #define INAM    ("intuition.library")
  46.  
  47. /* Global data, type and function declarations */
  48. typedef struct IntuitionBase* ib_t;
  49.  
  50. ib_t IntuitionBase=NULL;
  51. void *OpenLibrary();
  52.  
  53. FILE *ofp;
  54.  
  55. struct {
  56.     char filenam[NAMSIZ*10];
  57.     } fs;
  58.  
  59. struct namlist {
  60.     char *nam;
  61.     struct namlist *next;
  62.     } nlist;
  63.  
  64. /*
  65.     Acts like a state machine, the state of which
  66.     is determined by the combination of arguments
  67.     supplied.  The while loop sets the state, while
  68.     the if switches select action taken according
  69.     thereto.
  70. */
  71.  
  72. main(c, v)
  73. char **v;
  74. {
  75.     register active;
  76.     register err;
  77.     char *cdrive=NULL;
  78.     char *onam=NULL;
  79.     char bu[NAMSIZ*10];
  80.     char *getcd();
  81.     char *realnam();
  82.     void getrspinit(), freelist();
  83.  
  84.  
  85.     ++v;
  86.     while (**v == '-'){
  87.         switch(*++*v){
  88.             case 'o':   /* specify output file  */
  89.                 if (!*++v) {prerr(NULL, E_USAGE); exit(10);}
  90.                 else {onam=*v; ++v;}
  91.                 break;
  92.             case 'c':   /* continuous listing of 1 drive    */
  93.                 if (!*++v) {prerr(NULL, E_USAGE); exit(10);}
  94.                 else {cdrive=*v; ++v;}
  95.                 if (!(IntuitionBase=(ib_t)OpenLibrary(INAM, IREV))){
  96.                     prerr(NULL, E_LIBRARY); exit(10);
  97.                 }
  98.                 break;
  99.             default:
  100.                 prerr(NULL, E_USAGE);
  101.                 exit(10);
  102.         }
  103.     }
  104.  
  105.     if (onam){
  106.         if (!(ofp=fopen(onam, "w"))){
  107.             prerr(onam, E_OUTPUT);
  108.             exit(10);
  109.         }
  110.     }
  111.     else ofp=stdout;
  112.  
  113.     if (cdrive){
  114.         getrspinit();
  115.         if (getresponse()!=FALSE){
  116.             for (active=1; active; ){
  117.                 realnam(cdrive, fs.filenam);    /* seed pathname    */
  118.                 if (err=getnams(cdrive)) prerr(cdrive, err);
  119.                 if (getresponse()==FALSE) active=0;
  120.             }
  121.         }
  122.     }
  123.     else if (!*v){
  124.         getcd(bu);
  125.         strcpy(fs.filenam, bu);
  126.         if (err=getnams(bu)) prerr(bu, err);
  127.     }
  128.     else{
  129.         for (; *v; ++v){
  130.             realnam(*v, fs.filenam);            /* seed pathname    */
  131.             if (err=getnams(*v)) prerr(*v, err);
  132.         }
  133.     }
  134.     prlist(ofp, &nlist);
  135.     freelist(&nlist);
  136.     if (ofp!=stdout) fclose(ofp);
  137.     if (IntuitionBase) CloseLibrary(IntuitionBase);
  138.     exit(0);
  139. }
  140.  
  141. /*
  142.     If nam is the name of a file, add its size to the global counter.
  143.     If nam is the name of a directory, saunter down a level and
  144.     grab info for its files.
  145.     Return a coded description of any error which occurs, or zero
  146.     if success was the order of the day.
  147. */
  148.  
  149. getnams(nam)
  150. char *nam;
  151. {
  152.     register struct FileLock *l=NULL;
  153.     register struct FileInfoBlock *f=NULL;
  154.     register err=0;
  155.     struct FileLock *Lock();
  156.     void addtonam(), truncnam();
  157.  
  158.     if (!nam) return(E_NOEXAM);
  159.     if (!(l=Lock(nam, ACCESS_READ))){
  160.         return(E_NOLOCK);
  161.     }
  162.     if (!(f=(struct FileInfoBlock *)AllocMem((ULONG)sizeof(*f), MEMF_PUBLIC))) {
  163.         UnLock(l);
  164.         return(E_NOMEM);
  165.     }
  166.     if (!Examine(l, f)) {
  167.         UnLock(l);
  168.         FreeMem(f, (ULONG)sizeof(*f));
  169.         return(E_NOEXAM);
  170.     }
  171.     if (f->fib_DirEntryType<0){     /* file */
  172.         addnam(nam, &nlist);
  173.     }
  174.     else {
  175.         while (ExNext(l, f)){     /* directory    */
  176.             addtonam(fs.filenam, f->fib_FileName);
  177.             if (err=getnams(fs.filenam)) break;
  178.             truncnam(fs.filenam);        /* delete filename from path    */
  179.         }
  180.     }
  181.     UnLock(l);
  182.     FreeMem(f, (ULONG)sizeof(*f));
  183.     return(err);
  184. }
  185.  
  186. /*
  187.     Assuming p points to a valid pathname and s to a valid filename,
  188.     append the filename to the pathname.
  189. */
  190.  
  191. void
  192. addtonam(p, s)
  193. register char *p, *s;
  194. {
  195.     register char *op=p;
  196.  
  197.     while (*p)
  198.         p++;
  199.     if (p!=op){
  200.         if (*--p!=':')
  201.             *++p='/';
  202.         p++;
  203.     }
  204.     while (*s)
  205.         *p++=*s++;
  206.     *p='\0';
  207. }
  208.  
  209. /*
  210.     Assuming p points to a valid pathname, clip the filename from it.
  211. */
  212.  
  213. void
  214. truncnam(p)
  215. register char *p;
  216. {
  217.     register char *pp;
  218.  
  219.     if (!p) return;
  220.     for (pp=p; *pp; pp++)
  221.         ;
  222.     while (*pp!='/'&&*pp!=':'&&pp>p)
  223.         --pp;
  224.     if (*pp==':') ++pp;
  225.     *pp='\0';
  226. }
  227.  
  228. /*
  229.     Build a real pathname from the filename,
  230.     dirname, or drivename specifiecd in nam
  231.     into bu.  Return a pointer to bu on success,
  232.     or NULL if the chore is beyond doing.
  233. */
  234.  
  235. char *
  236. realnam(nam, bu)
  237. char *nam, *bu;
  238. {
  239.     register addcol;
  240.     register struct FileLock *l=NULL;
  241.     struct FileLock *Lock();
  242.  
  243.     if (!nam||!bu) return(NULL);
  244.     if (nam[strlen(nam)-1]==':') addcol=1;
  245.     else addcol=0;
  246.     if (!(l=Lock(nam, ACCESS_READ))){
  247.         return(NULL);
  248.     }
  249.     fullnam(l, bu);
  250.     UnLock(l);
  251.     return(bu);
  252. }
  253.  
  254.  
  255. /*
  256.     Put the full name of the current
  257.     directory into the supplied buffer
  258.     and return a pointer to it.
  259. */
  260.  
  261. char *
  262. getcd(bu)
  263. char *bu;
  264. {
  265.     struct FileLock *ol;
  266.  
  267.     if (!bu) return(NULL);
  268.     fullnam(ol=CurrentDir(0L), bu);
  269.     CurrentDir(ol);
  270.     return(bu);
  271. }
  272.  
  273. /*
  274.     Put the full pathname of a
  275.     locked file in the given buffer
  276.     and return a pointer to it.
  277. */
  278.  
  279. char *
  280. fullnam(l, bu)
  281. register struct FileLock *l;
  282. char *bu;
  283. {
  284.     register len;
  285.     struct FileLock *nl, *ParentDir();
  286.     char bu2[NAMSIZ];
  287.     char ebu[NAMSIZ*10];
  288.  
  289.     if (!l||!bu) return(NULL);
  290.     bu2[0]=0;
  291.     locknam(l, bu);
  292.     while (l=ParentDir(l)){
  293.         if (locknam(l, bu2)){
  294.             sprintf(ebu, "%s/%s", bu2, bu);
  295.             strcpy(bu, ebu);
  296.         }
  297.         else break;
  298.     }
  299.     if (bu2[0]) bu[strlen(bu2)]=':';
  300.     else {bu[len=strlen(bu)]=':'; bu[len+1]='\0';}
  301.     return(bu);
  302. }
  303.  
  304. /*
  305.     Put the name of the file or directory
  306.     associated with the given lock into
  307.     the given buffer and return a pointer
  308.     to it or NULL if it couldn't be done.
  309. */
  310.  
  311. char *
  312. locknam(l, bu)
  313. register struct FileLock *l;
  314. char *bu;
  315. {
  316.     register struct FileInfoBlock *f=NULL;
  317.  
  318.     if (!l||!bu) return(NULL);
  319.     if (!(f=(struct FileInfoBlock *)AllocMem((ULONG)sizeof(*f), MEMF_PUBLIC))) {
  320.         return(NULL);
  321.     }
  322.     if (!Examine(l, f)) {
  323.         FreeMem(f, (ULONG)sizeof(*f));
  324.         return(NULL);
  325.     }
  326.     strcpy(bu, f->fib_FileName);
  327.     FreeMem(f, (ULONG)sizeof(*f));
  328.     return(bu);
  329. }
  330.  
  331. /*
  332.     Add a name to the end of the filename list.
  333.     Could be more efficient, but the bottleneck
  334.     is disk speed.  Return a descriptive error
  335.     value on failure.
  336. */
  337.  
  338. addnam(s, lp)
  339. char *s;
  340. struct namlist *lp;
  341. {
  342.     struct namlist *newnode();
  343.     char *strsave();
  344.     void freelist(), prlist();
  345.  
  346.     if (!s||!lp) return(-1);
  347.     if (amtfree()<MEMFLOOR){        /* dump if mem full */
  348.         prlist(ofp, lp);
  349.         freelist(lp);
  350.     }
  351.     while (lp->next)
  352.         lp=lp->next;
  353.     if (!(lp->next=newnode()))
  354.         return(E_NONODE);    /* won't happen.  Better not.   */
  355.     if (!(lp->next->nam=strsave(s)))
  356.         return(E_NOSTRING);
  357.     return(0);
  358. }
  359.  
  360. /*
  361.     Allocate a new node for the filename list.
  362.     Return a pointer to it or NULL if there's
  363.     not enough memory.
  364. */
  365.  
  366. struct namlist *
  367. newnode()
  368. {
  369.     register struct namlist *mp;
  370.  
  371.     if (mp=(struct namlist *)malloc(sizeof(struct namlist))){
  372.         mp->nam=NULL;
  373.         mp->next=NULL;
  374.     }
  375.     return(mp);
  376. }
  377.  
  378. /*
  379.     Free the filename list.
  380. */
  381.  
  382. void
  383. freelist(lp)
  384. struct namlist *lp;
  385. {
  386.     struct namlist *p;
  387.  
  388.     if (!lp) return;
  389.     lp=lp->next;    /*  don't free 1st item */
  390.     while (lp){
  391.         p=lp->next;
  392.         free(lp->nam);
  393.         free(lp);
  394.         lp=p;
  395.     }
  396. }
  397.  
  398. /*
  399.     Print out the filename list.
  400. */
  401.  
  402. void
  403. prlist(fp, lp)
  404. FILE *fp;
  405. struct namlist *lp;
  406. {
  407.     if (!lp||!fp) return;
  408.     lp=lp->next;    /* don't print 1st item */
  409.     while (lp){
  410.         fprintf(fp, "%s\n", lp->nam);
  411.         lp=lp->next;
  412.     }
  413. }
  414.  
  415. /*
  416.     An old favorite.
  417. */
  418.  
  419. char *
  420. strsave(s)
  421. char *s;
  422. {
  423.     register len;
  424.     register char *mp;
  425.  
  426.     if (!s) return(NULL);
  427.     if (mp=malloc(len=strlen(s)+1))
  428.         memcpy(mp, s, len);
  429.     return(mp);
  430. }
  431.  
  432. /*
  433.     Report amount of free memory in the system.
  434.     Errors not allowed here.
  435. */
  436.  
  437. ULONG
  438. amtfree()
  439. {
  440.     ULONG c, f;
  441.  
  442.     Forbid();
  443.     c=AvailMem(MEMF_CHIP);
  444.     f=AvailMem(MEMF_FAST);
  445.     Permit();
  446.     return(c+f);
  447. }
  448.  
  449. /*
  450.     Print a message corresponding to the error given,
  451.     prompting with s, if nonnull.
  452.     Return the error given.
  453. */
  454.  
  455. prerr(s, err)
  456. char *s;
  457. {
  458.     register char *errp;
  459.  
  460.     switch (err){
  461.         case E_NOMEM:
  462.             errp="Out of memory"; break;
  463.         case E_NOEXAM:
  464.             errp="Couldn't examine"; break;
  465.         case E_NOLOCK:
  466.             errp="File not found"; break;
  467.         case E_OUTPUT:
  468.             errp="Can't open output file"; break;
  469.         case E_USAGE:
  470.             errp="Usage: qcat [-o outputfile] [-c drivename] or \n\
  471. qcat [-o outputfile] dirname";
  472.             break;
  473.         case E_LIBRARY:
  474.             errp="Couldn't open intuition.library";
  475.             break;
  476.         default:    /* NOTREACHED   */
  477.             errp="grievous error"; break;
  478.     }
  479.     if (s) printf("%s: %s\n", s, errp);
  480.     else printf("%s\n", errp);
  481.     return(err);
  482. }
  483.  
  484. /*
  485.     Set up the AutoRequest stuff, and use the
  486.     automatic requestor to tell the user when
  487.     to change disks, let them quit, and return
  488.     when they do so.
  489. */
  490.  
  491. char *rsp_bod0="Insert a disk";
  492. char *rsp_bod1="Next disk";
  493. char *rsp_no="Quit";
  494. char *rsp_yes="Redo";
  495.  
  496. struct response {
  497.     struct IntuiText bod;
  498.     struct IntuiText no;
  499.     ULONG yflg;
  500.     struct Window *w;
  501.     } rsp;
  502.  
  503. /*
  504.     Initialize the autorequestor's data and
  505.     find a window to put it in. Return nonzero
  506.     on failure, zero on success.
  507. */
  508.  
  509. getrspinit()
  510. {
  511.     rsp.bod.FrontPen=0;
  512.     rsp.bod.BackPen=1;
  513.     rsp.bod.DrawMode=JAM1;
  514.     rsp.bod.LeftEdge=6;
  515.     rsp.bod.TopEdge=3;
  516.     rsp.bod.ITextFont=NULL;
  517.     rsp.bod.IText=rsp_bod0;
  518.     rsp.bod.NextText=NULL;
  519.  
  520.     rsp.no=rsp.bod;
  521.     rsp.no.IText=rsp_no;
  522.  
  523.     rsp.yflg=DISKINSERTED;
  524.  
  525.     return(!(rsp.w=getCLIwin()));
  526. }
  527.  
  528. /*
  529.     Return a pointer to a window for
  530.     the requestor.  If there be none,
  531.     return NULL.
  532. */
  533.  
  534. struct Window *
  535. getCLIwin()
  536. {
  537.     register struct Screen *sp;
  538.     register struct Window *wp;
  539.  
  540.     return(IntuitionBase->ActiveWindow);
  541. }
  542.  
  543. /*
  544.     Post a requestor asking for a new
  545.     disk.  The first time called, just
  546.     ask for the first disk; after that,
  547.     ask for the next.  Return the boolean
  548.     value of the user's response.
  549. */
  550.  
  551. getresponse()
  552. {
  553.     register rv=0;
  554.  
  555.     rv=AutoRequest(rsp.w, &rsp.bod, NULL, &rsp.no, rsp.yflg, 0L, 200, 50);
  556.     rsp.bod.IText=rsp_bod1;
  557.     return(rv);
  558. }
  559.  
  560.  
  561.